
#include <iostream>
//using namespace std;

#include <boost/smart_ptr.hpp>
using namespace boost;

static void case1()
{
    shared_ptr<int> sp(new int(10));
    assert(sp.use_count() == 1);

    // 弱智能指针对象，不会改变shared_ptr的引用计数
    // 可解决shared_ptr循环引用导致内存泄漏问题
    weak_ptr<int> wp(sp);
    assert(wp.use_count() == 1);
    assert(!wp._empty());

    // 检查被引用的对象是否已删除 false 仍存在  true 释放
    if (!wp.expired())
    {
        shared_ptr<int> sp2 = wp.lock();
        *sp2 = 100;
        assert(wp.use_count() == 2);
    }

    assert(wp.use_count() == 1);
    // 释放被管理对象的所有权,调用后*this不管理对象
    sp.reset();
    assert(wp.expired());

    // 从被观测的shared_ptr获得一个可用的shared_ptr对象，从而操作资源
    assert(!wp.lock());
}

class self_shared:public enable_shared_from_this<self_shared>
{
public:
    self_shared(int n):x(n)
    {

    }

    int x;

    void print()
    {
        std::cout<<"self_shared:"<<x<<std::endl;
    }
};

static void case2()
{
    auto sp = make_shared<self_shared>(313);
    sp->print();

    // 返回当指向自身的share_ptr
    auto p = sp->shared_from_this();
    p->x = 1000;
    p->print();
    sp->print();
}

class node
{
public:
    ~node()
    {
        std::cout<<"deleted"<<std::endl;
    }

    typedef weak_ptr<node> ptr_type;
    ptr_type next;
};

static void case3()
{
    // 返回指定类型的std::shared_ptr
    auto p1 = make_shared<node>();
    auto p2 = make_shared<node>();

    p1->next = p2;
    p2->next = p1;

    assert(p1.use_count() == 1);
    assert(p2.use_count() == 1);

    // 功能等价于判断use_count是否等于0，但是速度更快
    if (!p1->next.expired())
    {
        // 获得一个和绑定的shared_ptr共享引用计数器的新的shared_ptr
        auto p3 = p1->next.lock();
    }
}

#include <boost/smart_ptr/enable_shared_from_raw.hpp>

class raw_shared:public enable_shared_from_raw
{
public:
    raw_shared()
    {
        std::cout<<"raw_shared ctor"<<std::endl;
    }
    ~raw_shared()
    {
        std::cout<<"raw_shared dtor"<<std::endl;
    }
};

static void case4()
{
    raw_shared x;
    assert(weak_from_raw(&x).use_count() == 1);

    auto px = shared_from_raw(&x);
    assert(px.use_count() == 2);

    auto p = new raw_shared;
    auto wp = weak_from_raw(p);
    assert(wp.use_count() == 1);

    decltype(shared_from_raw(p)) spx(p);
    auto sp = shared_from_raw(p);
    assert(sp.use_count() == 2);

    auto sp2 = sp;
    auto wp2 = weak_from_raw(p);
    assert(wp2.use_count() == 3);
}

int main()
{
    //case1();
    //case2();
    //case3();
    case4();
}

